#ifndef FIFO_PIPE_H
#define FIFO_PIPE_H

#include <condition_variable>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <mutex>
#include <queue>
#include <string>
#include <sys/stat.h>
#include <thread>
#include <unistd.h>

namespace utils {

class FifoPipe {
public:
  FifoPipe(const std::string &path) : fifoPath(path), stopThread(false) {
    if (mkfifo(fifoPath.c_str(), 0666) == -1) {
      std::cerr << "Error creating FIFO: " << strerror(errno) << std::endl;
    }

    workerThread = std::thread(&FifoPipe::processQueue, this);
  }

  ~FifoPipe() {
    stopThread = true;
    cv.notify_all();
    if (workerThread.joinable()) {
      workerThread.join();
    }

    if (unlink(fifoPath.c_str()) == -1) {
      std::cerr << "Error deleting FIFO: " << strerror(errno) << std::endl;
    }
  }

  void writeMessage(const std::string &message) {
    std::lock_guard<std::mutex> lock(queueMutex);
    messageQueue.push(message);
    cv.notify_one();
  }

private:
  std::string fifoPath;
  std::queue<std::string> messageQueue;
  std::thread workerThread;
  std::mutex queueMutex;
  std::condition_variable cv;
  bool stopThread;

  void processQueue() {
    while (!stopThread) {
      std::unique_lock<std::mutex> lock(queueMutex);
      cv.wait(lock, [this] { return !messageQueue.empty() || stopThread; });

      while (!messageQueue.empty()) {
        std::string message = messageQueue.front();
        messageQueue.pop();
        lock.unlock();

        int fd = open(fifoPath.c_str(), O_WRONLY);
        if (fd == -1) {
          std::cerr << "Error opening FIFO for writing: " << strerror(errno)
                    << std::endl;
        } else {
          write(fd, message.c_str(), message.size() + 1);
          // write(fd, "\n", 1);
          close(fd);
        }

        lock.lock();
      }
    }
  }
};
} // namespace utils

#endif